import 'dart:async';
import 'dart:typed_data';

import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:get/get.dart';
import 'package:sgy_flutter/ble/base_ble_manager.dart';
import 'package:sgy_flutter/ble/base_service.dart';
import 'package:sgy_flutter/ble/relay_stream_controller.dart';
import 'package:sgy_flutter/model/axo_data_model.dart';
import 'package:sgy_flutter/model/cycling_power_measurement_resp.dart';

/** Cycling Power Measurement
 * AXO魔改协议
 **/
class CyclingPowerService extends BaseService {
  static const _ServiceGuid = "00001818-0000-1000-8000-00805f9b34fb";

  static const _CyclingPowerMeasurementGuid =
      "00002a63-0000-1000-8000-00805f9b34fb";

  static const _CyclingPowerControlPointGuid =
      "00002a66-0000-1000-8000-00805f9b34fb";

  CyclingPowerService()
      : super(
            serviceGuid: _ServiceGuid,
            characteristicNotifyGuid: _CyclingPowerMeasurementGuid,
            characteristicReadGuid: null,
            characteristicWriteGuid: null);

  RelayStreamController<AxoDataModel?> resp =
      RelayStreamController(value: null);
  RelayStreamController<ByteData?> byteData =
      RelayStreamController(value: null);

  @override
  Future onCleanup() async {
    _lastCadence = null;
    _lastCadenceInterval = null;
    tp = 0;
    time = 0;
    resp.add(AxoDataModel(power: '--', cadence: '--', balance: '--'));
    byteData.add(null);
  }

  int? _lastCadence;
  int? _lastCadenceInterval;
  int tp = 0;
  int time = 0;

  @override
  FutureOr handleNotifyData(Uint8List data) {
    byteData.add(data.buffer.asByteData());
    if (data.length == 5) {
      //兼容老的DLS
      final byteData = data.buffer.asByteData();
      int currentTp = byteData.getUint16(1, Endian.little);
      int currentTime = byteData.getUint16(3, Endian.little);
      String cadence = "0";
      if (tp == 0 && time == 0) {
        time = currentTime;
        tp = currentTp;
      } else {
        if (currentTp - tp == 0) {
          cadence = ("0");
        } else {
          int myTp = (((currentTime - time < 0
                  ? currentTime - time + 65536
                  : currentTime - time) ~/
              (currentTp - tp)));
          if (myTp != 0) {
            cadence = "${61440 ~/ myTp}";
          }

          time = currentTime;
          tp = currentTp;
        }
      }

      this.resp.add(AxoDataModel(power: "--", cadence: cadence, balance: "--"));
    } else {
      final byteData = data.buffer.asByteData();
      CyclingPowerMeasurementResp resp = CyclingPowerMeasurementResp(
        flag: byteData.getUint16(0, Endian.big),
        power: byteData.getUint16(2, Endian.little),
        balance: byteData.getUint8(4),
        cadence: byteData.getUint16(5, Endian.little),
        cadenceInterval: byteData.getUint16(7, Endian.little),
        totalPower: byteData.getUint16(9, Endian.little),
      );
      String power = ("${resp.power}");
      var value = resp.balance ?? 0;
      String balance =
          ("${(value / 2).toStringAsFixed(0)}/${(100 - value / 2).toStringAsFixed(0)}");
      String cadenceStr = "0";
      if (_lastCadence != null && _lastCadenceInterval != null) {
        final cadence = resp.cadence ?? 0;
        final cadenceInterval = resp.cadenceInterval ?? 0;
        var n = cadenceInterval - _lastCadenceInterval! < 0
            ? cadenceInterval - _lastCadenceInterval! + 65536
            : cadenceInterval - _lastCadenceInterval!;
        if (61400 / (n / (cadence - _lastCadence!)) >= 0) {
          cadenceStr =
              ("${(61400 / (n / (cadence - _lastCadence!))).toStringAsFixed(0)}");
        }
      }

      _lastCadence = resp.cadence;
      _lastCadenceInterval = resp.cadenceInterval;

      this.resp.add(
          AxoDataModel(power: power, cadence: cadenceStr, balance: balance));
    }
  }
}
